//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <stdio.h>

#include <guidseed.h>

_ELASTOS_NAMESPACE_USING

UInt32 GetWordValue(
    const DictWord *pDict, const wchar_t *pwszSeed, UInt32 *pValue)
{
    UInt32 n = 0;

    while (0 != pDict[n].nSize) {
        if (!wcsncmp(pDict[n].pwszWord, pwszSeed, pDict[n].nSize)) {
            *pValue = n + 64;
            return pDict[n].nSize;
        }
        n++;
    }
    *pValue = EncodeCSymbol(*pwszSeed);
    return 1;
}

UInt32 GetWordByValue(
    const DictWord *pDict, UInt32 dwValue, wchar_t *pResult)
{
    if (dwValue < 64) {
        *pResult = (wchar_t)DecodeCSymbol(dwValue);
        return 1;
    }
    dwValue -= 64;
    memcpy(pResult, pDict[dwValue].pwszWord, pDict[dwValue].nSize * 2);
    return pDict[dwValue].nSize;
}

IMPL_GUID_ENCODE(StaticDict)(
    void *pvArg, const wchar_t *pwszSeed, UInt32 *pResult)
{
    UInt32 dwValue, dwOffset;
    UInt32 cCount, cMatched, cEncoded;
    UInt32 *pPrevResult, dwPrevOffset;

    *pResult = EncodeCSymbol(*pwszSeed++);
    cCount = 0;
    cEncoded = 1;
    dwOffset = dwPrevOffset = 6;
    pPrevResult = pResult;

    while (0 != *pwszSeed) {
        cMatched = GetWordValue((DictWord *)pvArg, pwszSeed, &dwValue);
        pwszSeed += cMatched;
        cEncoded += cMatched;

        *pResult |= dwValue << dwOffset;
        dwOffset += 9;

        if (dwOffset >= 32) {
            if (2 == cCount) break;
            cCount++;
            pResult++;
            dwOffset -= 32;
            *pResult |= dwValue >> (9 - dwOffset);
        }
    }

    if (cCount < 2) {
        while (TRUE) {
            dwValue = (*pPrevResult >> dwPrevOffset) & 0x1ff;
            dwPrevOffset += 9;
            if (dwPrevOffset >= 32) {
                pPrevResult++;
                dwPrevOffset -= 32;
                dwValue |= (*pPrevResult << (9 - dwPrevOffset)) & 0x1ff;
            }

            *pResult |= dwValue << dwOffset;
            dwOffset += 9;

            if (dwOffset >= 32) {
                if (2 == cCount) break;
                cCount++;
                pResult++;
                dwOffset -= 32;
                *pResult |= dwValue >> (9 - dwOffset);
            }
        }
    }
    return cEncoded;
}

IMPL_GUID_DECODE(StaticDict)(
    void *pvArg, const UInt32 *pSource, wchar_t *pwszResult)
{
    UInt32 cCount, dwOffset, dwValue;

    *pwszResult++ = (wchar_t)DecodeCSymbol(*pSource & 0x3f);
    cCount = 0;
    dwOffset = 6;

    while (TRUE) {
        dwValue = (*pSource >> dwOffset) & 0x1ff;
        dwOffset += 9;
        if (dwOffset >= 32) {
            if (2 == cCount) break;
            cCount++;
            pSource++;
            dwOffset -= 32;
            dwValue |= (*pSource << (9 - dwOffset)) & 0x1ff;
        }
        pwszResult += GetWordByValue((DictWord *)pvArg, dwValue, pwszResult);
    }

    *pwszResult = 0;
    return 0;
}
